/* 
** (Copyright) sejishikong <sejishikong@263.net>
** Authors:    sejishikong <sejishikong@263.net>
**             Wei Lian <lianwei2003.student@sina.com> 
** Maintainer: Wei Lian
**    This program is free software; you can redistribute it and/or modify
**    it under the terms of the GNU General Public License Version 2 as
**    published by the Free Software Foundation;
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program; if not, write to the Free Software
**    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
*/

#include "sys.h"
#include "fork.h"
#include "record.h"
#include "header.h"
#include "config.h"
#include "channel.h"
#include "timing.h"
#include "mainwindow.h"
#include "menubar.h"

Record::Record(QWidget * parent, const char *name):QHBox(parent, name),
mainwindow(static_cast < Sopcast * >(parent))
{
    recordfp = new QFile();
    snrecord = 0;

    launchtimer = new QTimer(this);
    connect(launchtimer, SIGNAL(timeout()), this, SLOT(launchRecord()));

    quittimer = new QTimer(this);
    connect(quittimer, SIGNAL(timeout()), this, SLOT(quitRecord()));

    ///status bar
    statusbar = new QStatusBar(this);
    statusbar->setSizeGripEnabled(false);
    statusbar->hide();
    ///input for timing
    timing = new Timing(this);
    ///button record
    buttonrecord = new QToolButton(this);
    buttonrecord->setTextLabel("Record");
    buttonrecord->setAutoRaise(true);
    buttonrecord->setUsesTextLabel(true);
    buttonrecord->setToggleButton(TRUE);
    //signal
    connect(buttonrecord, SIGNAL(toggled(bool)), this,
	    SLOT(onButtonRecordToggled(bool)));

}

Record::~Record()
{
    if (snrecord) {
	recordfp->close();
	::close(snrecord->socket());
	delete snrecord;
	snrecord = 0;
    }
    delete recordfp;
}


void
 Record::streamReady(int fd)
{
    int ret;
    char buff[1024];
    ret =::read(fd, buff, sizeof(buff));
    if (ret <= 0) {
	if (ret < 0)
	    perror("record socketnotifier");

	recordfp->close();
	::close(fd);
	delete snrecord;
	snrecord = 0;
	buttonrecord->setPaletteForegroundColor(Qt::black);

	/////restart record
	launchtimer->start(2000, true);

	return;
    }
    ::write(recordfp->handle(), buff, ret);
}


void Record::launchRecord()
{
    ////handle sp-sc
    if (!mainwindow->fork->sop->isRunning()) {
	if (mainwindow->fork->forksop(channelurl, channelname) == TRUE) {
	    ///add to history
	    mainwindow->menubar->addToPopupMenu(mainwindow->menubar->
						history, channelurl,
						channelname);
	} else
	    fprintf(stderr, "failed to launch sp-sc!\n");
    } else if (mainwindow->fork->channelurl != channelurl) {
	mainwindow->fork->killsop();
	if (mainwindow->fork->forksop(channelurl, channelname) == TRUE) {
	    ///add to history
	    mainwindow->menubar->addToPopupMenu(mainwindow->menubar->
						history, channelurl,
						channelname);
	} else
	    fprintf(stderr, "failed to launch sp-sc!\n");
    }
    ////handle stream
    int sockfd = Sys::connect_to_server("127.0.0.1",
					atoi(mainwindow->fork->outport));
    if (sockfd < 0) {
	///restart
	launchtimer->start(2000, true);
	return;
    }
    ::write(sockfd, "1",::strlen("1") + 1);
    ///parse header
    char buf[19];
    if (::recv(sockfd, buf, sizeof(buf), 0) != sizeof(buf)) {
	fprintf(stderr, "err while parsing head\n");
	::close(sockfd);
	buttonrecord->setOn(false);
	return;
    }
    ///testing data availibility
    int nread;
    ::ioctl(sockfd, FIONREAD, &nread);
    if (nread <= 0) {
	::close(sockfd);
	////
	if (nread < 0)
	    perror("ioctl get nread of socket");
	///restart
	launchtimer->start(2000, true);
	return;
    }
    ////data availible
    QString data_path = mainwindow->vboxconfig->editrecorddir->text();
    QDir dir(data_path);
    if (!dir.exists())
	if (!dir.mkdir(data_path)) {
	    perror("failed to create record path");
	    ::close(sockfd);
	    buttonrecord->setOn(false);
	    return;
	}
    data_path += mainwindow->fork->channelname.replace(QRegExp("\\/+"), "#");	///eliminate harmful character
    data_path += QDateTime::currentDateTime().toString();
    data_path += ".asf";
    recordfp->setName(data_path);
    if (!recordfp->open(IO_WriteOnly)) {
	perror("record file name is invalid");
	::close(sockfd);
	buttonrecord->setOn(false);
	return;
    }
    if (snrecord) {
	fprintf(stderr, "QSocketNotifier exist!\n");
	return;
    }
    snrecord = new QSocketNotifier(sockfd, QSocketNotifier::Read, this);
    connect(snrecord, SIGNAL(activated(int)), SLOT(streamReady(int)));

    buttonrecord->setPaletteForegroundColor(Qt::red);
}

void Record::quitRecord()
{
    buttonrecord->setOn(false);

}

void Record::onButtonRecordToggled(bool t)
{
    if (t) {
	if (!mainwindow->channel->currentItem()) {
	    buttonrecord->setOn(false);
	    return;
	}
	if (mainwindow->channel->currentItem()->depth() != 1) {
	    buttonrecord->setOn(false);
	    return;
	}
	///get channel name and url
	channelname =
	    mainwindow->channel->currentItem()->text(NAME_COLUMN);
	channelurl = mainwindow->channel->currentItem()->text(URL_COLUMN);
	///get time for current, from and to
	int current =
	    QTime::currentTime().hour() * 60 * 60 +
	    QTime::currentTime().minute() * 60 +
	    QTime::currentTime().second();
	int from =
	    timing->fromHour->text().toInt() * 60 * 60 +
	    timing->fromMinute->text().toInt() * 60;
	int to =
	    timing->toHour->text().toInt() * 60 * 60 +
	    timing->toMinute->text().toInt() * 60;
	///calculate delay time for record start and stop
	int delaystart, delaystop;
	QString fromdaytime, todaytime;
	if (timing->fromHour->text().isEmpty()
	    && timing->toHour->text().isEmpty()) {
	    delaystart = 0;
	    delaystop = -1;
	    ///
	    fromdaytime = "today/now";
	    todaytime = "inf";
	} else if (timing->fromHour->text().isEmpty()) {
	    delaystart = 0;
	    delaystop =
		to - current >=
		0 ? to - current : to - current + 24 * 60 * 60;
	    ///
	    fromdaytime = "today/now";
	    todaytime = to - current >= 0 ? "today/" : "tomor/";
	    todaytime +=
		timing->toHour->text() + ":" + timing->toMinute->text();
	    ///
	} else if (timing->toHour->text().isEmpty()) {
	    delaystart =
		from - current >=
		0 ? from - current : from - current + 24 * 60 * 60;
	    delaystop = -1;
	    ///
	    fromdaytime = from - current >= 0 ? "today/" : "tomor/";
	    fromdaytime +=
		timing->fromHour->text() + ":" +
		timing->fromMinute->text();
	    todaytime = "inf";
	    ///
	} else {
	    delaystart =
		from - current >=
		0 ? from - current : from - current + 24 * 60 * 60;
	    delaystop =
		to - from >= 0 ? to - from : to - from + 24 * 60 * 60;
	    delaystop = delaystop + delaystart;
	    ///
	    fromdaytime = from - current >= 0 ? "today/" : "tomor/";
	    fromdaytime +=
		timing->fromHour->text() + ":" +
		timing->fromMinute->text();
	    switch ((from - current < 0) + (to - from < 0)) {
	    case 0:
		todaytime = "today/";
		break;
	    case 1:
		todaytime = "tomor/";
		break;
	    case 2:
		todaytime = "aftto/";
	    }
	    todaytime +=
		timing->toHour->text() + ":" + timing->toMinute->text();
	}
	///start timer for starting record
	launchtimer->start(delaystart * 1000, true);
	///start timer for stoping record
	if (delaystop >= 0) {
	    quittimer->start(delaystop * 1000, true);
	}
	///change interface
	statusbar->message(fromdaytime + "-" + todaytime + "|" +
			   channelname);
	statusbar->show();
	timing->hide();
	///log
	printf("record start after %d hour and %d minute %d second\n",
	       delaystart / 3600, delaystart / 60 % 60, delaystart % 60);
	if (delaystop >= 0)
	    printf("   and stop after %d hour and %d minute %d second\n",
		   delaystop / 3600, delaystop / 60 % 60, delaystop % 60);
    } else			///function setOn(false) will trigger the following code
    {
	///close file, socket and socketnotifier
	if (snrecord) {
	    recordfp->close();
	    ::close(snrecord->socket());
	    delete snrecord;
	    snrecord = 0;
	}
	///reset button color
	buttonrecord->setPaletteForegroundColor(Qt::black);
	///stop timer
	launchtimer->stop();
	quittimer->stop();
	///change interface
	statusbar->hide();
	timing->show();
    }

}
